/***********************************************************/
/*        code in this file runs in real mode              */
/*        it's the first stage of monitor                  */
/***********************************************************/

#include "base.h"
#include "monitor.h"

struct _sys_info sys_info = {
	.kern_hdr_offset = 0xFFFFFFFF,
	.kern_entry = 0xFFFFFFFF,
	.e820_num = 0,
	.e820 = {[0 ... 63] = {.addr_low = 0,
		                   .addr_high = 0,
	                       .size_low = 0,
						   .size_high = 0,
						   .type = 0}
						   }
};

/*************************************************/
/*                                               */
/*        boot parameter get                     */
/*                                               */
/*************************************************/
asm(".code16\n");

#define SMAP	0x534D4150

/* get the physical memory layout by using E820 */
int get_memory_e820(void){
	uint_32 e820_entry = (uint_32)sys_info.e820;
	uint_32 smap;
	uint_32 next = 1;
	uint_8 err = 0;

	for (; next && !err;){
		__asm__("movl %3, %%edi;		\n\t"
				"movl $0x0000E820,%%eax;		\n\t"
				"movl $0x14,%%ecx;		\n\t"
				"movl $0x534D4150,%%edx;		\n\t"
				"int $0x15;		\n\t"
				"setc %0;	\n\t"
				"movl %%eax, %1;	\n\t"
				"movl %%ebx, %2;	\n\t"
				:"=m"(err),"=m"(smap),"=m"(next)
				:"m"(e820_entry));

		if (err){
			sys_info.e820_num = 0;
			break;
		}

		if (smap != SMAP){
			sys_info.e820_num = 0;
			break;
		}

		sys_info.e820_num ++;
		e820_entry += sizeof(struct mem_e820);
	}

	return 0;
}

int fast_a20(void){
	__asm__("movw $0x2401, %ax;	\n\t"
			"int $0x15;	\n\t"
			);
	return 0;
}

int a20_status(void){
	__asm__("mov $0x92,%dx;	\n\t"
			"inb %dx,%al;	\n\t"
			"andb $0x02,%al;	\n\t"
			);

	return 0;
}

struct driver{
	uint_8 cylinder;
	uint_8 sector;
	uint_8 header;
};

uint_16 seg;
uint_16 offset;
uint_16 num;

struct driver hd;

int do_load(void){
	uint_8 status;
	uint_8 err;
	
	__asm__ __volatile__ ("movw %2, %%ax;		\n\t"
			"movw %%ax,%%es;		\n\t"
			"movw %3,%%bx;		\n\t"
			"movb $0x02, %%ah;	\n\t"
			"movb %4, %%al;		\n\t"
			"movb %5, %%ch;		\n\t"
			"movb %6, %%cl;		\n\t"
			"movb %7, %%dh;		\n\t"
			"movb $0x80, %%dl;		\n\t"
			"int $0x13;		\n\t"
			"setc %0;	\n\t"
			"movb %%ah, %1;	\n\t"
			:"=m"(err),"=m"(status)
			:"m"(seg),"m"(offset),"m"(num),"m"(hd.cylinder),
			 "m"(hd.sector),"m"(hd.header)
			);

	if (err || status){
		return 1;
	}

	return 0;
}

/* first we load the first track that include 0x39 sectors
 * then we load the whole second track
 */
int load_kernel(void){
	seg = (uint_16)0x800;
	offset = (uint_16)0x0;
	num = (uint_16) 0x3F;
	
	hd.cylinder = 0x0;
	hd.sector = 0x1;
	hd.header = 0x1;
	do_load();
	
	seg = (uint_16)0x800;
	offset = (uint_16)(0x3F * 512);
	num = (uint_16) 0x3F;
	
	hd.cylinder = 0x0;
	hd.sector = 0x1;
	hd.header = 0x2;
	do_load();
	
	return 0;
}

/* EOF */

